package com.cloud.common.support;

import lombok.extern.slf4j.Slf4j;
import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.annotation.Around;
import org.aspectj.lang.annotation.Aspect;
import org.springframework.core.Ordered;
import org.springframework.core.annotation.Order;
import org.springframework.stereotype.Component;

import java.util.concurrent.LinkedBlockingQueue;
import java.util.concurrent.ThreadPoolExecutor;
import java.util.concurrent.TimeUnit;

@Slf4j
@Aspect
@Order(Ordered.HIGHEST_PRECEDENCE)
@Component
public class AsyncInterceptor {

    private ThreadPoolExecutor executor;

    @Around("@annotation(org.springframework.scheduling.annotation.Async)")
    public Object doAsync(ProceedingJoinPoint point) {
        if (executor == null) {
            createExecutor();
        }
        executor.execute(() -> {
            try {
                point.proceed();
            } catch (Throwable t) {
                log.error(t.getMessage(), t);
            }
        });
        return null;
    }

    private synchronized void createExecutor() {
        if (executor == null) {
            int poolSize = Runtime.getRuntime().availableProcessors();
            executor = new DefaultThreadPoolExecutor(poolSize, poolSize, 180, TimeUnit.SECONDS, new LinkedBlockingQueue<>());
        }
    }
}
